<!DOCTYPE html>
<html lang=zh>
<head><meta name="generator" content="Hexo 3.9.0">
    <!-- so meta -->
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="HandheldFriendly" content="True">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <meta name="description" content="前言最近连续加了一个星期的班，每天回去烧个热水，边泡脚边刷段子（此处有拖拉机般的笑声，哈哈），然后就上床睡觉了。至于加班的原由嘛，是在开发一个类似百万英雄的活动页面。就在昨天晚上任务上线部署了，于是我今天也就有时间总结总结。 如何使用 vue 开发多页面vue 拥有基于 vue-router 的强大路由，基于 vuex 的页面状态管理，以及基于 webpack 的打包工具 vue-cli，在构建单">
<meta name="keywords" content="vue,同花顺">
<meta property="og:type" content="article">
<meta property="og:title" content="使用vue开发多页面的活动页面">
<meta property="og:url" content="https://andyliwr.github.io/2018/02/12/vue_multiple_pages_develop/index.html">
<meta property="og:site_name" content="月光倾城的代码小屋">
<meta property="og:description" content="前言最近连续加了一个星期的班，每天回去烧个热水，边泡脚边刷段子（此处有拖拉机般的笑声，哈哈），然后就上床睡觉了。至于加班的原由嘛，是在开发一个类似百万英雄的活动页面。就在昨天晚上任务上线部署了，于是我今天也就有时间总结总结。 如何使用 vue 开发多页面vue 拥有基于 vue-router 的强大路由，基于 vuex 的页面状态管理，以及基于 webpack 的打包工具 vue-cli，在构建单">
<meta property="og:locale" content="zh-CN">
<meta property="og:image" content="https://file.lantingshucheng.com/blog/2018/02/12/invite_alert.PNG">
<meta property="og:updated_time" content="2020-01-15T06:30:09.120Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="使用vue开发多页面的活动页面">
<meta name="twitter:description" content="前言最近连续加了一个星期的班，每天回去烧个热水，边泡脚边刷段子（此处有拖拉机般的笑声，哈哈），然后就上床睡觉了。至于加班的原由嘛，是在开发一个类似百万英雄的活动页面。就在昨天晚上任务上线部署了，于是我今天也就有时间总结总结。 如何使用 vue 开发多页面vue 拥有基于 vue-router 的强大路由，基于 vuex 的页面状态管理，以及基于 webpack 的打包工具 vue-cli，在构建单">
<meta name="twitter:image" content="https://file.lantingshucheng.com/blog/2018/02/12/invite_alert.PNG">
    
    
        
          
              <link rel="shortcut icon" href="/images/favicon.ico">
          
        
        
          
            <link rel="icon" type="image/png" href="/images/favicon-192x192.png" sizes="192x192">
          
        
        
          
            <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon.png">
          
        
    
    <!-- title -->
    <title>使用vue开发多页面的活动页面</title>
    <!-- styles -->
    <link rel="stylesheet" href="/css/style.css">
    <!-- persian styles -->
    
      <link rel="stylesheet" href="/css/rtl.css">
    
    <!-- rss -->
    
    
</head>

<body class="max-width mx-auto px3 ltr">
    
      <div id="header-post">
  <a id="menu-icon" href="#"><i class="fas fa-bars fa-lg"></i></a>
  <a id="menu-icon-tablet" href="#"><i class="fas fa-bars fa-lg"></i></a>
  <a id="top-icon-tablet" href="#" onclick="$('html, body').animate({ scrollTop: 0 }, 'fast');" style="display:none;"><i class="fas fa-chevron-up fa-lg"></i></a>
  <span id="menu">
    <span id="nav">
      <ul>
         
          <li><a href="/">首页</a></li>
         
          <li><a href="/archives/">归档</a></li>
         
          <li><a href="/search/">搜索</a></li>
         
          <li><a href="/tags/">标签</a></li>
         
          <li><a href="/others/">其他文章</a></li>
        
      </ul>
    </span>
    <br/>
    <span id="actions">
      <ul>
        
        <li><a class="icon" href="/2018/04/23/node_canvas_usage/"><i class="fas fa-chevron-left" aria-hidden="true" onmouseover="$('#i-prev').toggle();" onmouseout="$('#i-prev').toggle();"></i></a></li>
        
        
        <li><a class="icon" href="/2018/01/12/js_call_apply/"><i class="fas fa-chevron-right" aria-hidden="true" onmouseover="$('#i-next').toggle();" onmouseout="$('#i-next').toggle();"></i></a></li>
        
        <li><a class="icon" href="#" onclick="$('html, body').animate({ scrollTop: 0 }, 'fast');"><i class="fas fa-chevron-up" aria-hidden="true" onmouseover="$('#i-top').toggle();" onmouseout="$('#i-top').toggle();"></i></a></li>
        <li><a class="icon" href="#"><i class="fas fa-share-alt" aria-hidden="true" onmouseover="$('#i-share').toggle();" onmouseout="$('#i-share').toggle();" onclick="$('#share').toggle();return false;"></i></a></li>
      </ul>
      <span id="i-prev" class="info" style="display:none;">上一篇</span>
      <span id="i-next" class="info" style="display:none;">下一篇</span>
      <span id="i-top" class="info" style="display:none;">返回顶部</span>
      <span id="i-share" class="info" style="display:none;">分享文章</span>
    </span>
    <br/>
    <div id="share" style="display: none">
      <ul>
  <li><a class="icon" href="http://www.facebook.com/sharer.php?u=https://andyliwr.github.io/2018/02/12/vue_multiple_pages_develop/"><i class="fab fa-facebook " aria-hidden="true"></i></a></li>
  <li><a class="icon" href="https://twitter.com/share?url=https://andyliwr.github.io/2018/02/12/vue_multiple_pages_develop/&text=使用vue开发多页面的活动页面"><i class="fab fa-twitter " aria-hidden="true"></i></a></li>
  <li><a class="icon" href="http://www.linkedin.com/shareArticle?url=https://andyliwr.github.io/2018/02/12/vue_multiple_pages_develop/&title=使用vue开发多页面的活动页面"><i class="fab fa-linkedin " aria-hidden="true"></i></a></li>
  <li><a class="icon" href="https://pinterest.com/pin/create/bookmarklet/?url=https://andyliwr.github.io/2018/02/12/vue_multiple_pages_develop/&is_video=false&description=使用vue开发多页面的活动页面"><i class="fab fa-pinterest " aria-hidden="true"></i></a></li>
  <li><a class="icon" href="mailto:?subject=使用vue开发多页面的活动页面&body=Check out this article: https://andyliwr.github.io/2018/02/12/vue_multiple_pages_develop/"><i class="fas fa-envelope " aria-hidden="true"></i></a></li>
  <li><a class="icon" href="https://getpocket.com/save?url=https://andyliwr.github.io/2018/02/12/vue_multiple_pages_develop/&title=使用vue开发多页面的活动页面"><i class="fab fa-get-pocket " aria-hidden="true"></i></a></li>
  <li><a class="icon" href="http://reddit.com/submit?url=https://andyliwr.github.io/2018/02/12/vue_multiple_pages_develop/&title=使用vue开发多页面的活动页面"><i class="fab fa-reddit " aria-hidden="true"></i></a></li>
  <li><a class="icon" href="http://www.stumbleupon.com/submit?url=https://andyliwr.github.io/2018/02/12/vue_multiple_pages_develop/&title=使用vue开发多页面的活动页面"><i class="fab fa-stumbleupon " aria-hidden="true"></i></a></li>
  <li><a class="icon" href="http://digg.com/submit?url=https://andyliwr.github.io/2018/02/12/vue_multiple_pages_develop/&title=使用vue开发多页面的活动页面"><i class="fab fa-digg " aria-hidden="true"></i></a></li>
  <li><a class="icon" href="http://www.tumblr.com/share/link?url=https://andyliwr.github.io/2018/02/12/vue_multiple_pages_develop/&name=使用vue开发多页面的活动页面&description="><i class="fab fa-tumblr " aria-hidden="true"></i></a></li>
</ul>

    </div>
    <div id="toc">
      <ol class="toc"><li class="toc-item toc-level-3"><a class="toc-link" href="#前言"><span class="toc-number">1.</span> <span class="toc-text">前言</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#如何使用-vue-开发多页面"><span class="toc-number">2.</span> <span class="toc-text">如何使用 vue 开发多页面</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#如何使用-vue-写一个弹窗组件"><span class="toc-number">3.</span> <span class="toc-text">如何使用 vue 写一个弹窗组件</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#弹窗状态管理"><span class="toc-number">3.1.</span> <span class="toc-text">弹窗状态管理</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#关闭弹窗功能-closeAlert-实现"><span class="toc-number">3.2.</span> <span class="toc-text">关闭弹窗功能(closeAlert)实现</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#如何在点击弹窗中的按钮触发一个新的弹窗"><span class="toc-number">3.3.</span> <span class="toc-text">如何在点击弹窗中的按钮触发一个新的弹窗</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#如何使得弹窗居中"><span class="toc-number">3.4.</span> <span class="toc-text">如何使得弹窗居中</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#验证码组件"><span class="toc-number">4.</span> <span class="toc-text">验证码组件</span></a></li></ol>
    </div>
  </span>
</div>

    
    <div class="content index py4">
        
        <article class="post" itemscope itemtype="http://schema.org/BlogPosting">
  <header>
    
    <h1 class="posttitle" itemprop="name headline">
        使用vue开发多页面的活动页面
    </h1>



    <div class="meta">
      <span class="author" itemprop="author" itemscope itemtype="http://schema.org/Person">
        <span itemprop="name">月光倾城的代码小屋</span>
      </span>
      
    <div class="postdate">
        <time datetime="2018-02-12T11:02:44.000Z" itemprop="datePublished">2018-02-12</time>
    </div>


      

      
    <div class="article-tag">
        <i class="fas fa-tag"></i>
        <a class="tag-link" href="/tags/vue/">vue</a>, <a class="tag-link" href="/tags/同花顺/">同花顺</a>
    </div>


    </div>
  </header>
  

  <div class="content" itemprop="articleBody">
    <h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>最近连续加了一个星期的班，每天回去烧个热水，边泡脚边刷段子（此处有拖拉机般的笑声，哈哈），然后就上床睡觉了。至于加班的原由嘛，是在开发一个类似百万英雄的活动页面。就在昨天晚上任务上线部署了，于是我今天也就有时间总结总结。</p>
<h3 id="如何使用-vue-开发多页面"><a href="#如何使用-vue-开发多页面" class="headerlink" title="如何使用 vue 开发多页面"></a>如何使用 vue 开发多页面</h3><p>vue 拥有基于 vue-router 的强大路由，基于 vuex 的页面状态管理，以及基于 webpack 的打包工具 vue-cli，在构建单页面应用上可谓 6 得飞起。无奈的是很多原生应用在加载 H5 页面的时候都是有导航条的，这样用户一点击导航条上的返回键，就直接退出了 H5 页面，并不能实现按下返回键返回到上一层路由。但是 webpack 既然能打包单页面，那就一定能打包多页面，只不过需要自己做些额外的配置。这里我直接推荐大神的 github 项目了，框架一定要选好，不然运行不起来或者打包之后出错就很尴尬了。</p>
<figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">git</span> <span class="string">clone https://github.com/zzuieliyaoli/vue-multi-pages-application-boilerplate.git</span></span><br><span class="line"><span class="attr">cd</span> <span class="string">vue-multi-pages-application-boilerplate</span></span><br><span class="line"><span class="attr">cnpm</span> <span class="string">install</span></span><br><span class="line"><span class="comment"># 测试是否能正常运行</span></span><br><span class="line"><span class="attr">npm</span> <span class="string">run dev</span></span><br><span class="line"><span class="comment"># 测试打包之后的文件能否在app里运行</span></span><br><span class="line"><span class="attr">npm</span> <span class="string">run build</span></span><br><span class="line"><span class="comment"># 将dist目录的下的文件上传到ftp，使用app打开H5页面</span></span><br><span class="line"><span class="attr">https</span>:<span class="string">//khtest.10jqka.com.cn/dev/lidikang/sg_cddh/index.html</span></span><br></pre></td></tr></table></figure>
<p><strong>使用方法:</strong><br>多页面路由管理在<code>build/entries.js</code>中，每次新建一个页面就在<code>src/</code>下新建一个<code>xxx.html</code>和一个<code>xxx.entry.js</code>，并且在<code>src/pages</code>建好对应的<code>vue</code>文件<code>xxx.vue</code>和入口 js<code>index.js</code>，最后在这个<code>build/entries.js</code>里添加一行，键值名为页面名称，键值为对应的<code>xxx.entry.js</code>的路径。</p>
<h3 id="如何使用-vue-写一个弹窗组件"><a href="#如何使用-vue-写一个弹窗组件" class="headerlink" title="如何使用 vue 写一个弹窗组件"></a>如何使用 vue 写一个弹窗组件</h3><p>活动页面的弹窗通常都是经过 UI 美化过的，所以需要自己去定义各种布局和样式。但是如果每个弹窗我们都去设置灰色背景，弹窗位置这样就显得太过麻烦，所以可以使用 vue 新建一个弹窗组件来专门管理弹窗这块的功能。需要解决的问题如下：</p>
<ol>
<li>每个弹窗文字、样式、按钮、按钮点击的回调、发送的埋点都不一样，如何统一管理</li>
<li>每个弹窗内容不一样，所以高度也不一样，如果使用 css 的 transform 或者 flex 布局使得弹窗居中当然很简单，但是低端设备就不行了，有没有更好的垂直水平居中方案？</li>
</ol>
<h4 id="弹窗状态管理"><a href="#弹窗状态管理" class="headerlink" title="弹窗状态管理"></a>弹窗状态管理</h4><p>触发打开弹窗的操作一般在具体的活动页面（当然也可能有点击之后触发一个新的弹窗，这个稍后再议），我们只需要将弹窗的标题，需要展示的 html，以及按钮文字，按钮点击触发的回调函数，这些自定义项传给 Alert 组件就好了。比如：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">&lt;alert :data=<span class="string">"alert"</span>&gt;<span class="xml"><span class="tag">&lt;/<span class="name">alert</span>&gt;</span></span></span><br><span class="line">-------------------------------</span><br><span class="line"><span class="keyword">this</span>.alert = &#123;</span><br><span class="line">  show: <span class="literal">true</span>,</span><br><span class="line">  className: <span class="string">'general-text'</span>,</span><br><span class="line">  text: <span class="string">'这是一段测试的段落'</span>,</span><br><span class="line">  btnText: <span class="string">'确认'</span>,</span><br><span class="line">  btnCallback: <span class="keyword">this</span>.closeAlert</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>但是这样会带来新的问题，像稍微复杂一点的弹窗，比如需要展示手机号码输入框这些，它们本身就带有一些监听事件，直接定义在 html 字符串里，在渲染 Alert 组件的时候是无效的。因此对于复杂的弹窗，我们直接在 Alert 组件将它写好，并使用自定义的弹窗 ID 来控制它们的显隐。比如：</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"alert-container"</span> <span class="attr">v-show</span>=<span class="string">"data.show"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"content"</span> <span class="attr">ref</span>=<span class="string">"content"</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"title"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">span</span> <span class="attr">v-html</span>=<span class="string">"data.title"</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span> <span class="comment">&lt;!--标题--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">i</span> <span class="attr">class</span>=<span class="string">"iconfont icon-close"</span> @<span class="attr">click</span>=<span class="string">"closeAlert"</span>&gt;</span><span class="tag">&lt;/<span class="name">i</span>&gt;</span> <span class="comment">&lt;!--关闭按钮--&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 常规文字提示 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"general-text"</span> <span class="attr">v-if</span>=<span class="string">"data.className === 'general-text'"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">"des"</span> <span class="attr">v-html</span>=<span class="string">"data.text"</span>&gt;</span><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"alert-btn"</span> <span class="attr">v-if</span>=<span class="string">"data.btnText.length &gt; 0"</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">"data.btnCallback"</span>&gt;</span>&#123;&#123;data.btnText&#125;&#125;<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 资格校验 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"zige"</span> <span class="attr">v-if</span>=<span class="string">"data.className === 'zige'"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"des-container"</span>&gt;</span><span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">"des"</span>&gt;</span>请填写开户时使用的手机号进行身份验证<span class="tag">&lt;/<span class="name">p</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"form"</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"form-group"</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">input</span> <span class="attr">v-model</span>=<span class="string">"telphone"</span> <span class="attr">type</span>=<span class="string">"tel"</span> <span class="attr">id</span>=<span class="string">"telphone"</span> <span class="attr">placeholder</span>=<span class="string">"请输入您的手机号"</span> @<span class="attr">input</span>=<span class="string">"telphoneInput($event)"</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">"err-tip"</span>&gt;</span>&#123;&#123;telPhoneError&#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">:class</span>=<span class="string">"&#123;'alert-btn': true, 'disabled': !isTelPhoneRight&#125;"</span>&gt;</span><span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">"doZigeCheck"</span>&gt;</span>确定<span class="tag">&lt;/<span class="name">button</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>这样当你传过来的 data 的<code>className</code>属性是<code>&quot;zige&quot;</code>的时候就会去渲染验证领奖资格的弹窗，这个时候你就能在 Alert 组件里定义 input 的处理事件。</p>
<figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">this</span>.alert = &#123;</span><br><span class="line">  <span class="keyword">show</span>: <span class="keyword">true</span>,</span><br><span class="line">  className: <span class="string">'zige'</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="关闭弹窗功能-closeAlert-实现"><a href="#关闭弹窗功能-closeAlert-实现" class="headerlink" title="关闭弹窗功能(closeAlert)实现"></a>关闭弹窗功能(closeAlert)实现</h4><p>在弹窗的<code>container</code>上加上<code>v-show</code>的属性（这里为什么用 v-show 而不使用 v-if，稍后说），使用<code>data.show</code>的字段来控制弹窗的显隐，但是<code>data</code>是父级传给<code>Alert</code>的，在<code>Aler</code>t 组件中并不能直接修改<code>data</code>的值，所以需要和父级约定一个<code>closeAlert</code>的方法，在 Alert 组件中使用<code>this.$emit(&#39;close&#39;)</code>报告关闭弹窗的请求后，父级再接受到<code>close</code>的请求，并将传递给<code>Alert</code>的<code>data</code>值中的<code>show</code>改成<code>false</code>，这样就实现了弹窗的隐藏。</p>
<figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;alert :<span class="attribute">data</span>=<span class="string">"alert"</span> @<span class="attribute">close</span>=<span class="string">"closeAlert"</span>&gt;&lt;/alert&gt;</span><br></pre></td></tr></table></figure>
<h4 id="如何在点击弹窗中的按钮触发一个新的弹窗"><a href="#如何在点击弹窗中的按钮触发一个新的弹窗" class="headerlink" title="如何在点击弹窗中的按钮触发一个新的弹窗"></a>如何在点击弹窗中的按钮触发一个新的弹窗</h4><p>实现原理其实和上面差不多，就是和父级约定一个<code>openNewAlert</code>的方法，在 Alert 组件中报告<code>openNewAlert</code>的事件，并把新的弹窗参数传递给父级。父级接收参数，并将传给 Alert 的参数改成新的参数。</p>
<figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">&lt;alert :<span class="attribute">data</span>=<span class="string">"alert"</span> @<span class="attribute">close</span>=<span class="string">"openNewAlert"</span>&gt;&lt;/alert&gt;</span><br><span class="line">------------------------------------------------</span><br><span class="line">openNewAlert()&#123;</span><br><span class="line">  this.<span class="variable">$emit</span>(<span class="string">'openNewAlert'</span>, &#123;</span><br><span class="line">    show: <span class="literal">true</span>,</span><br><span class="line">    title: <span class="string">'新弹窗'</span>,</span><br><span class="line">    className: <span class="string">'general-text'</span>,</span><br><span class="line">    text: <span class="string">'这是一段测试文字'</span></span><br><span class="line">    <span class="built_in">..</span><span class="built_in">..</span></span><br><span class="line">  &#125;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="如何使得弹窗居中"><a href="#如何使得弹窗居中" class="headerlink" title="如何使得弹窗居中"></a>如何使得弹窗居中</h4><p>在<code>css3</code>中使得一个不确定高度的盒子居中有很多方法，最常见的就是使用<code>transform</code>和<code>flex</code>布局，但是很遗憾，<code>transfrom</code>在<code>iphone5</code>和<code>android4.4</code>的测试机上行不通，<code>flex</code>布局哪怕兼容了-webkit-box 在<code>android4.1</code>上也没法使用。我们知道，如果我们清楚弹窗的高度，垂直居中就变得很简单，只需要将它的<code>margin-top</code>值设置为负的高度的一半就行。那能不能在弹窗弹出的瞬间动态计算它的高度，然后动态设置它的<code>margin-top</code>值呢？技术上是没问题的，vue 只要在需要获取的 dom 上加上<code>ref=&quot;xxx&quot;</code>，在函数里就能通过<code>this.$refs.xxx.offsetHeight</code>来获取它的高度，但是这样有两个问题：</p>
<ol>
<li>计算弹窗高度的触发函数是什么？弹窗的 mounted 事件？或者 watch 事件？</li>
<li>如果弹窗中包含 img 标签，vue 并不会等待图片加载好了才去触发计算弹窗高度的触发函数，这样就会导致计算出来的高度偏小，弹窗最后并未居中，如何修复？</li>
</ol>
<p>因为只有当传过来的 alert.show 的值为 true 的时候，才会去动态计算 alert 的高度，所以放在 watch 方法里更合适，虽然 mounted 方法貌似也行，但是由于使用的 v-show 所以弹窗在渲染的时候 mounted 只执行一次。为了保证<code>this.$refs.content</code>不为空，这里最好放在<code>vm.$nextTick</code>的里执行。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">watch: &#123;</span><br><span class="line">  data(newValue, oldValue)&#123;</span><br><span class="line">    <span class="comment">// 只有在newValue为true的时候才去动态计算弹窗的动态高度</span></span><br><span class="line">    <span class="keyword">if</span>(newValue.show)&#123;</span><br><span class="line">      <span class="keyword">this</span>.$nextTick(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">        <span class="keyword">let</span> self = <span class="keyword">this</span></span><br><span class="line">        <span class="keyword">this</span>.$refs.content.style.marginTop = (-<span class="keyword">this</span>.$refs.content.offsetHeight/<span class="number">2</span>) + <span class="string">'px'</span>;</span><br><span class="line">      &#125;);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;,</span><br></pre></td></tr></table></figure>
<p>第二个问题 vue 并不会等待图片加载好了才去触发计算弹窗高度的触发函数是因为我们使用的 v-if 来控制弹窗的显示隐藏，而 v-if 只有当条件为真的时候才开始渲染弹窗，这样就慢了。我们使用 v-show，这样即使条件为假，vue 也会去渲染弹窗，等你打开弹窗的时候既不会出现图片还在加载中的情况，高度自然也就不会计算错误。</p>
<h3 id="验证码组件"><a href="#验证码组件" class="headerlink" title="验证码组件"></a>验证码组件</h3><p>活动页面有一个弹窗需要用户输入对方的邀请码，样子如下：<br><img src="https://file.lantingshucheng.com/blog/2018/02/12/invite_alert.PNG" alt="邀请码"></p>
<p>实现的原理如下，将 input 定义在 label 里，然后将 input 隐藏（这里 android 和 ios 的处理方法不一样），最后在 label 中添加 ul，每当输入一个字符串，就把 ul 中的一个 li 的值改成新输入的值。我这里没有实现方块里的光标提示的功能，这个要实现得话估计得自己模拟光标了。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"> <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"invite"</span> <span class="attr">v-if</span>=<span class="string">"data.className === 'invite'"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"invite-text"</span>&gt;</span>填写好友的邀请码，你与TA都将获得1张复活卡<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"invite-code-wrap"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">label</span> <span class="attr">for</span>=<span class="string">"code"</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">ul</span> <span class="attr">class</span>=<span class="string">"invite-code-container"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">li</span> <span class="attr">class</span>=<span class="string">"field-wrap"</span> <span class="attr">v-for</span>=<span class="string">"(item, index) in inviteCodeNum"</span> <span class="attr">:key</span>=<span class="string">"index"</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">i</span> <span class="attr">class</span>=<span class="string">"char-field number-font"</span>&gt;</span>&#123;&#123;inviteCode[index] || ''&#125;&#125;<span class="tag">&lt;/<span class="name">i</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">label</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">input</span> <span class="attr">ref</span>=<span class="string">"input"</span> <span class="attr">class</span>=<span class="string">"input-code"</span> @<span class="attr">input</span>=<span class="string">"inviteCodeInput($event)"</span> <span class="attr">v-model</span>=<span class="string">"inviteCode"</span> <span class="attr">id</span>=<span class="string">"code"</span> <span class="attr">name</span>=<span class="string">"code"</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">:maxlength</span>=<span class="string">"inviteCodeNum"</span> <span class="attr">autofocus</span>=<span class="string">"autofocus"</span> <span class="attr">autocorrect</span>=<span class="string">"off"</span> <span class="attr">autocomplete</span>=<span class="string">"off"</span></span></span><br><span class="line"><span class="tag">        <span class="attr">autocapitalize</span>=<span class="string">"characters"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">:class</span>=<span class="string">"&#123;'alert-btn': true, 'disabled': !isInviteCodeRight&#125;"</span>&gt;</span><span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">"acceptInvite"</span>&gt;</span>确定<span class="tag">&lt;/<span class="name">button</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>android 和 ios 隐藏 input 应该使用不同的方法：</p>
<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.alert-container</span> <span class="selector-class">.invite</span> <span class="selector-class">.input-code</span><span class="selector-class">.gphone</span> &#123;</span><br><span class="line">  <span class="attribute">position</span>: absolute;</span><br><span class="line">  <span class="attribute">top</span>: -<span class="number">9999px</span>;</span><br><span class="line">  <span class="attribute">left</span>: -<span class="number">9999px</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.alert-container</span> <span class="selector-class">.invite</span> <span class="selector-class">.input-code</span><span class="selector-class">.iphone</span> &#123;</span><br><span class="line">  <span class="attribute">height</span>: <span class="number">0</span>;</span><br><span class="line">  <span class="attribute">opacity</span>: <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>最后附上项目地址：<a href="http://gitlab.khweb.com/lidikang/millions-hero" target="_blank" rel="noopener">millions-hero</a></p>

  </div>
  <div class="statement">
    <hr>  
    1. 如果本文帮到了您，不妨点一下右上角的”<i class="fas fa-share-alt"></i>“按钮。<br>
    2. 除非注明，本博文章均为原创，转载请以链接形式标明本文地址。<br>
    3. 如果你有任何疑问，欢迎发送邮件到我的邮箱<a href="mailto:andyliwr@outlook.com">andyliwr@outlook.com<br>
  </div>
</article>


    <div class="blog-post-comments">
        <div id="gitalk_thread">
            <noscript>加载评论需要在浏览器启用 JavaScript 脚本支持。</noscript>
        </div>
    </div>



        
          <div id="footer-post-container">
  <div id="footer-post">

    <div id="nav-footer" style="display: none">
      <ul>
         
          <li><a href="/">首页</a></li>
         
          <li><a href="/archives/">归档</a></li>
         
          <li><a href="/search/">搜索</a></li>
         
          <li><a href="/tags/">标签</a></li>
         
          <li><a href="/others/">其他文章</a></li>
        
      </ul>
    </div>

    <div id="toc-footer" style="display: none">
      <ol class="toc"><li class="toc-item toc-level-3"><a class="toc-link" href="#前言"><span class="toc-number">1.</span> <span class="toc-text">前言</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#如何使用-vue-开发多页面"><span class="toc-number">2.</span> <span class="toc-text">如何使用 vue 开发多页面</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#如何使用-vue-写一个弹窗组件"><span class="toc-number">3.</span> <span class="toc-text">如何使用 vue 写一个弹窗组件</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#弹窗状态管理"><span class="toc-number">3.1.</span> <span class="toc-text">弹窗状态管理</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#关闭弹窗功能-closeAlert-实现"><span class="toc-number">3.2.</span> <span class="toc-text">关闭弹窗功能(closeAlert)实现</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#如何在点击弹窗中的按钮触发一个新的弹窗"><span class="toc-number">3.3.</span> <span class="toc-text">如何在点击弹窗中的按钮触发一个新的弹窗</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#如何使得弹窗居中"><span class="toc-number">3.4.</span> <span class="toc-text">如何使得弹窗居中</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#验证码组件"><span class="toc-number">4.</span> <span class="toc-text">验证码组件</span></a></li></ol>
    </div>

    <div id="share-footer" style="display: none">
      <ul>
  <li><a class="icon" href="http://www.facebook.com/sharer.php?u=https://andyliwr.github.io/2018/02/12/vue_multiple_pages_develop/"><i class="fab fa-facebook fa-lg" aria-hidden="true"></i></a></li>
  <li><a class="icon" href="https://twitter.com/share?url=https://andyliwr.github.io/2018/02/12/vue_multiple_pages_develop/&text=使用vue开发多页面的活动页面"><i class="fab fa-twitter fa-lg" aria-hidden="true"></i></a></li>
  <li><a class="icon" href="http://www.linkedin.com/shareArticle?url=https://andyliwr.github.io/2018/02/12/vue_multiple_pages_develop/&title=使用vue开发多页面的活动页面"><i class="fab fa-linkedin fa-lg" aria-hidden="true"></i></a></li>
  <li><a class="icon" href="https://pinterest.com/pin/create/bookmarklet/?url=https://andyliwr.github.io/2018/02/12/vue_multiple_pages_develop/&is_video=false&description=使用vue开发多页面的活动页面"><i class="fab fa-pinterest fa-lg" aria-hidden="true"></i></a></li>
  <li><a class="icon" href="mailto:?subject=使用vue开发多页面的活动页面&body=Check out this article: https://andyliwr.github.io/2018/02/12/vue_multiple_pages_develop/"><i class="fas fa-envelope fa-lg" aria-hidden="true"></i></a></li>
  <li><a class="icon" href="https://getpocket.com/save?url=https://andyliwr.github.io/2018/02/12/vue_multiple_pages_develop/&title=使用vue开发多页面的活动页面"><i class="fab fa-get-pocket fa-lg" aria-hidden="true"></i></a></li>
  <li><a class="icon" href="http://reddit.com/submit?url=https://andyliwr.github.io/2018/02/12/vue_multiple_pages_develop/&title=使用vue开发多页面的活动页面"><i class="fab fa-reddit fa-lg" aria-hidden="true"></i></a></li>
  <li><a class="icon" href="http://www.stumbleupon.com/submit?url=https://andyliwr.github.io/2018/02/12/vue_multiple_pages_develop/&title=使用vue开发多页面的活动页面"><i class="fab fa-stumbleupon fa-lg" aria-hidden="true"></i></a></li>
  <li><a class="icon" href="http://digg.com/submit?url=https://andyliwr.github.io/2018/02/12/vue_multiple_pages_develop/&title=使用vue开发多页面的活动页面"><i class="fab fa-digg fa-lg" aria-hidden="true"></i></a></li>
  <li><a class="icon" href="http://www.tumblr.com/share/link?url=https://andyliwr.github.io/2018/02/12/vue_multiple_pages_develop/&name=使用vue开发多页面的活动页面&description="><i class="fab fa-tumblr fa-lg" aria-hidden="true"></i></a></li>
</ul>

    </div>

    <div id="actions-footer">
        <a id="menu" class="icon" href="#" onclick="$('#nav-footer').toggle();return false;"><i class="fas fa-bars fa-lg" aria-hidden="true"></i> 菜单</a>
        <a id="toc" class="icon" href="#" onclick="$('#toc-footer').toggle();return false;"><i class="fas fa-list fa-lg" aria-hidden="true"></i> 目录</a>
        <a id="share" class="icon" href="#" onclick="$('#share-footer').toggle();return false;"><i class="fas fa-share-alt fa-lg" aria-hidden="true"></i> 分享</a>
        <a id="top" style="display:none" class="icon" href="#" onclick="$('html, body').animate({ scrollTop: 0 }, 'fast');"><i class="fas fa-chevron-up fa-lg" aria-hidden="true"></i> 返回顶部</a>
    </div>

  </div>
</div>

        
        <footer id="footer">
  <div class="footer-left">
    Copyright &copy; 2020 Dikang Li
  </div>
  <div class="footer-right">
    <nav>
      <ul>
         
          <li><a href="/">首页</a></li>
         
          <li><a href="/archives/">归档</a></li>
         
          <li><a href="/search/">搜索</a></li>
         
          <li><a href="/tags/">标签</a></li>
         
          <li><a href="/others/">其他文章</a></li>
        
      </ul>
    </nav>
  </div>
</footer>

    </div>
</body>
</html>
<!-- styles -->
<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">
<link rel="stylesheet" href="/lib/justified-gallery/css/justifiedGallery.min.css">
<link rel="stylesheet" href="/lib/fancybox/jquery.fancybox.css">

<link rel="stylesheet" href="https://file.lantingshucheng.com/blog/v3/static/styles/gitalk.css">


<!-- jquery -->
<script src="/lib/jquery/jquery.min.js"></script>
<script src="/lib/justified-gallery/js/jquery.justifiedGallery.min.js"></script>
<script src="/lib/fancybox/jquery.fancybox.pack.js"></script>

<script type="text/javascript" src="https://file.lantingshucheng.com/blog/v3/static/scripts/md5.js"></script>
<script type="text/javascript" src="https://file.lantingshucheng.com/blog/v3/static/scripts/gitalk.min.js"></script>

<script src="/js/main.js"></script>
<!-- search -->

<!-- Google Analytics -->

<!-- Baidu Analytics -->

    <script type="text/javascript">
        var _hmt = _hmt || [];
        (function() {
            var hm = document.createElement("script");
            hm.src = "https://hm.baidu.com/hm.js?7851ca7a86be957be994acb77639a5be";
            var s = document.getElementsByTagName("script")[0];
            s.parentNode.insertBefore(hm, s);
        })();
    </script>

<!-- Disqus Comments -->


  <script type="text/javascript">
    window.onload = function(){
      if (window.location.href.indexOf('andyliwr.github.io') > -1) {
        var gitalk = new Gitalk({
          clientID: 'ad6f70df0c70d2b715f9',
          clientSecret: '40384bee244c1e17dd7c37733d21e9ef669e969c',
          repo: 'Andyliwr.github.io',
          owner: 'Andyliwr',
          admin: ['Andyliwr'],
          id: md5(location.pathname),
          distractionFreeMode: 'true'
        })
        gitalk.render('gitalk_thread')
      }
    }
  </script>


